package com.threeox.ormlibrary.util;

import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.text.TextUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.threeox.ormlibrary.db.OrmDatabaseManager;
import com.threeox.ormlibrary.entity.TableMsg;
import com.threeox.utillibrary.util.Basic2ObjUtil;
import com.threeox.utillibrary.util.EmptyUtils;
import com.threeox.utillibrary.util.LogUtils;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/** 
 *
 * @ClassName: DataBaseUtil
 *
 * @Description: (数据库操作的工具类)
 *
 * @author 赵屈犇
 *
 * @date 创建时间:2016/12/16 15:47 
 * 
 * @version 1.0
 */
@SuppressLint("NewApi")
@SuppressWarnings({"rawtypes", "unchecked"})
@Deprecated
public class DataBaseUtil {

    public static final String TAG = DataBaseUtil.class.getName();

    /**
     * 保存多条数据
     *
     * @param datas
     * @param tableName
     * @return
     */
    public static Long save(List datas, String tableName) {
        Long startTime = System.currentTimeMillis();
        LogUtils.e(tableName + "开始插入" + datas.size() + "条数据,开始时间:" + startTime);
        if (!EmptyUtils.isEmpty(datas)) {
            SQLiteDatabase db = OrmDatabaseManager.getInstance().getWritableDatabase();
            try {
                db.beginTransaction();
                for (Object data : datas) {
                    save(data, tableName);
                }
                db.setTransactionSuccessful();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                db.endTransaction();
            }
        }
        Long stopTime = System.currentTimeMillis();
        LogUtils.d(tableName + "结束插入" + datas.size() + "条数据,结束时间:" + stopTime);
        LogUtils.d(tableName + "用时:" + (stopTime - startTime));
        return 0L;
    }

    /**
     * 根据对象保存数据
     *
     * @param data
     * @param tableName
     * @return
     */
    public static Long save(Object data, String tableName) {
        return save(data, tableName, null);
    }

    /**
     * 根据对象保存数据
     *
     * @param data
     * @param tableName
     * @return
     */
    public static Long save(Object data, String tableName, SQLiteDatabase db) {
        ContentValues contentValues = objToValues(data, tableName);
        if (db == null) {
            db = OrmDatabaseManager.getInstance().getWritableDatabase();
        }
        try {
            return db.insert(tableName, null, contentValues);
        } catch (Exception e) {
            LogUtils.e(TAG, tableName + "表添加失败!");
            return null;
        }
    }

    public static int deleteAll(String tableName) {
        return delete(tableName, null);
    }

    /**
     * 删除全部数据
     *
     * @param tableName
     * @return
     */
    public static int delete(String tableName, String whereClause, String... whereArgs) {
        try {
            return OrmDatabaseManager.getInstance().getWritableDatabase().delete(tableName, whereClause, whereArgs);
        } catch (Exception e) {
            return -1;
        }
    }

    /**
     * 更新输入
     *
     * @param tableName
     * @param values
     * @param whereClause
     * @param whereArgs
     */
    public static int update(String tableName, ContentValues values,
                             String whereClause, String... whereArgs) {
        try {
            return OrmDatabaseManager.getInstance().getWritableDatabase()
                    .update(tableName, values, whereClause, whereArgs);
        } catch (Exception e) {
            return -1;
        }
    }

    /**
     * 更新表数据
     *
     * @param tableName
     * @param data
     * @param whereClause
     * @param whereArgs
     * @return
     */
    public static int update(String tableName, Object data, String whereClause, String... whereArgs) {
        ContentValues values = objToValues(data, tableName);
        return OrmDatabaseManager.getInstance().getWritableDatabase().update(tableName, values, whereClause, whereArgs);
    }

    /**
     * 查询成为集合
     *
     * @param sql
     * @param clazz
     * @param selectionArgs
     * @return
     */
    public static List queryList(String sql, Class clazz, String... selectionArgs) {
        SQLiteDatabase db = OrmDatabaseManager.getInstance().getReadableDatabase();
        Cursor cursor = db.rawQuery(sql, selectionArgs);
        return cursorToList(cursor, clazz);
    }

    /**
     * 永远只查询一条数据
     *
     * @param sql
     * @param clazz
     * @return
     */
    public static <T extends Object> T queryObject(String sql, Class clazz) {
        return queryObject(sql, clazz);
    }

    /**
     * 永远只查询一条数据
     *
     * @param sql
     * @param clazz
     * @return
     */
    public static <T extends Object> T queryObject(String sql, Class clazz,  String... selectionArgs) {
        SQLiteDatabase db = OrmDatabaseManager.getInstance().getReadableDatabase();
        Cursor cursor = db.rawQuery(sql, selectionArgs);
        if (cursor == null)
            return null;
        if (cursor.getCount() == 0) {
            cursor.close();
            return null;
        }
        cursor.moveToNext();
        return (T) cursorToObj(cursor, clazz);
    }

    /**
     * 将Cursor 反射为集合
     *
     * @param cursor
     * @param clazz
     * @return
     */
    public static List cursorToList(Cursor cursor, Class clazz) {
        if (cursor == null)
            return null;
        if (cursor.getCount() == 0) {
            cursor.close();
            return null;
        }
        List list = new ArrayList();
        while (cursor.moveToNext()) {
            list.add(cursorToObj(cursor, clazz));
        }
        cursor.close();
        return list;
    }

    /**
     * 将Cursor 反射为对象
     *
     * @param c
     * @param clazz
     * @return
     */
    private static Object cursorToObj(Cursor c, Class clazz) {
        try {
            // 得到列的数组
            String[] columnNames = c.getColumnNames();
            // 实例化对象
            Object newInstance = clazz.newInstance();
            if (newInstance instanceof JSONObject) {
                for (String columnName : columnNames) {
                    String val = c.getString(c.getColumnIndex(columnName));
                    if (!TextUtils.isEmpty(val)) {
                        ((JSONObject) newInstance).put(columnName, val);
                    }
                }
            } else {
                // 得到所有的字段
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {
                    Class<? extends Object> typeClass = field.getType();
                    String fieldName = field.getName();
                    typeClass = Basic2ObjUtil.getInstance().getBasicClass(typeClass);
                    for (String columnName : columnNames) {
                        // 判断值是否一致
                        if (columnName.equalsIgnoreCase(fieldName)) {
                            Object _Val = null;
                            String val = c.getString(c.getColumnIndex(columnName));
                            if (isBasicType(typeClass)) {
                                if (!TextUtils.isEmpty(val)) {
                                    Constructor<? extends Object> cons = typeClass.getConstructor(String.class);
                                    _Val = cons.newInstance(val);
                                }
                            } else {
                                try {
                                    if (typeClass.getSimpleName().equals("List")) {
                                        _Val = JSON.parseArray(val);
                                    } else {
                                        _Val = JSON.parseObject(val, typeClass);
                                    }
                                    LogUtils.e(TAG, "注入" + typeClass + "对象成功");
                                } catch (Exception e) {
                                    LogUtils.e(TAG, "注入" + typeClass + "对象失败!数据库保存数据请传入JSON" + val);
                                }
                            }
                            if (_Val != null) {
                                field.setAccessible(true);
                                field.set(newInstance, _Val);
                            }
                        }
                    }
                }
            }
            return newInstance;
        } catch (Exception e) {
            LogUtils.e(DataBaseUtil.class, e.getMessage());
        }
        return null;
    }

    /**
     * ContentValues 转为对象
     *
     * @param values
     * @param obj
     * @param <T>
     * @return
     */
    public static <T extends Object> T valueToObj(ContentValues values, Object obj) {
        try {
            if (values != null) {
                Class<? extends Object> cls = obj.getClass();
                Field[] fields = cls.getDeclaredFields();
                Set<String> set = values.keySet();
                for (String key : set) {
                    for (Field field : fields) {
                        if (key.equals(field.getName())) {
                            field.setAccessible(true);
                            field.set(obj, values.get(key));
                        }
                    }
                }
                return (T) obj;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return (T) obj;
    }

    /**
     * 根据对象转为ContentValues
     *
     * @param data
     * @param tableName
     * @return
     */
    private static ContentValues objToValues(Object data, String tableName) {
        TableMsg tableMsg = TableUtil.getTableMsgByKey(tableName);
        String[] columnNames = tableMsg.getColumnNames();
        Class<? extends Object> clazz = data.getClass();
        ContentValues contentValues = new ContentValues();
        for (String columnName : columnNames) {
            try {
                Object invoke = null;
                if (data instanceof JSONObject) {
                    invoke = ((JSONObject) data).get(columnName);
                } else {
                    columnName = DBBaseUtil.captureName(columnName);
                    Method method = clazz.getMethod("get" + columnName);
                    invoke = method.invoke(data);
                }
                if (invoke != null) {
                    if (invoke instanceof Integer) {
                        contentValues.put(columnName, (Integer) invoke);
                    } else if (invoke instanceof Long) {
                        contentValues.put(columnName, (Long) invoke);
                    } else if (invoke instanceof Float) {
                        contentValues.put(columnName, (Float) invoke);
                    } else if (invoke instanceof Byte) {
                        contentValues.put(columnName, (Byte) invoke);
                    } else if (invoke instanceof Short) {
                        contentValues.put(columnName, (Short) invoke);
                    } else if (invoke instanceof Double) {
                        contentValues.put(columnName, (Double) invoke);
                    } else if (invoke instanceof String) {
                        contentValues.put(columnName, (String) invoke);
                    } else if (invoke instanceof Boolean) {
                        contentValues.put(columnName, (Boolean) invoke);
                    } else if ("byte[]".equals(invoke.getClass()
                            .getSimpleName())) {
                        contentValues.put(columnName, (byte[]) invoke);
                    } else if (invoke instanceof Object) {
                        contentValues
                                .put(columnName, JSON.toJSONString(invoke));
                    } else {
                        LogUtils.e(TAG, columnName + "插入失败:save");
                    }
                } else {
                    LogUtils.e(TAG, columnName + "没有值:save");
                }
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
                LogUtils.e(TAG, "找不到get" + columnName + "方法:" + e.getMessage());
            } catch (Exception e) {
                e.printStackTrace();
                LogUtils.e(TAG, "save方法:" + e.getMessage());
            }
        }
        return contentValues;
    }

    /**
     * 判断是不是基本类型
     *
     * @param typeClass
     * @return
     */
    private static boolean isBasicType(Class typeClass) {
        if (typeClass.equals(Integer.class) || typeClass.equals(Long.class)
                || typeClass.equals(Float.class)
                || typeClass.equals(Double.class)
                || typeClass.equals(Boolean.class)
                || typeClass.equals(Byte.class)
                || typeClass.equals(Short.class)
                || typeClass.equals(String.class)) {
            return true;
        } else {
            return false;
        }
    }

}
